package net.xuele.learn.lock;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Author: yubo
 * @date: 9:25 2020/4/15
 * @Description: 类描述:
 *   CompletionService：任务先完成可优先获取到，即结果按照完成先后顺序排序；
 *   它是Executor和BlockingQueue功能的融合体，Executor完成计算任务，BlockingQueue负责保存异步任务的执行结果
 */

public class TestCompletionService {

    public static void main(String[] args) {
        //开启3个线程
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        try {
            int taskCount = 10;
            // 结果集
            List<Integer> list = new ArrayList<Integer>();
            List<Future<Integer>> futureList = new ArrayList<Future<Integer>>();

            // 1.定义CompletionService
            CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(executorService);

            // 2.添加任务
            for (int i = 0; i < taskCount; i++) {
                // 里面有一个BlockingQueue
                // task将会被封装成FutureTask，在任务完成的时候（Future的finishCompletion()方法），会调用done方法，
                // 这个done方法将完成的这个任务添加到了阻塞队列中
                Future<Integer> future = completionService.submit(new Task(i + 1));
                futureList.add(future);
            }

            // 3.获取结果
            for (int i = 0; i < taskCount; i++) {
                Integer result = completionService.take().get();
                System.out.println("任务i==" + result + "完成!" + new Date());
                list.add(result);
            }

            System.out.println("list=" + list);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭线程池
            executorService.shutdown();
        }
    }

    private static class Task implements Callable<Integer> {
        private int i;

        public Task(int i) {
            super();
            this.i = i;
        }

        @Override
        public Integer call() throws Exception {
            if (i == 5) {
                Thread.sleep(5000);
            } else {
                Thread.sleep(1000);
            }
            System.out.println("线程：" + Thread.currentThread().getName() + "任务i= " + i + ", 执行完成！");
            return i;
        }
    }
}
